package com.mall.util;

import io.jsonwebtoken.*;
import org.apache.logging.log4j.util.Base64Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JWTUtil {
    private static Logger logger = LoggerFactory.getLogger(JWTUtil.class);

        private final static String secretKey= "654321";
        //生成JWT token


    public static Claims parseJwt(String jsonWebToken){
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(secretKey))
                    .parseClaimsJws(jsonWebToken).getBody();
            return claims;
        } catch (ExpiredJwtException e){
            logger.error("===token过期===");

        } catch (MalformedJwtException e){
            logger.error("====json web token格式错误====");

        }catch (Exception e){
            logger.error("=====token解析异常=====");

        }
        return null;
    }


            /**
             * 构建jwt
             * @param userId 用户id
             * @param username jwt的所有者
             * @param role 权限
             */
            public static String createToken(String userId, String username, String role) {
                try {//使用HS256加密算法
                    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

                    //生成签名
                    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secretKey);
                    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
                    //userId是重要的信息，进行简要加密下
                    String encryId = Base64Util.encode(userId);
                    Map<String, Object> map = new HashMap<>();
                    map.put("alg", "HS256");
                    map.put("typ", "JWT");

                    //添加构成JWT的参数
                    JwtBuilder jwtBuilder = Jwts.builder().setHeader(map)
                            //可以将基本不重要的对象信息放到claims
                            .claim("role", role)
                            .claim("userId", encryId)
                            .setSubject(username)   //代表这个jwt的主体，即它的所有人
                            .setIssuer("com.cyzy")  //代表这个jwt的签发主体
                            .setIssuedAt(new Date())    //一个时间戳，代表签发时间
                            .setAudience("name")    //代表jwt的接收对象
                            .signWith(signatureAlgorithm, signingKey);
                    //添加token过期时间
                    int expiresMillis = 3600000;
                    if (expiresMillis >= 0) {
                        Long nowMillis = System.currentTimeMillis();
                        Date now = new Date(nowMillis);
                        long expMillis = nowMillis + expiresMillis;
                        Date expireTime = new Date(expMillis);
                        jwtBuilder.setExpiration(expireTime)   //是一个时间戳，代表jwt的过期时间
                                .setNotBefore(now);     //是一个时间戳，代表这个jwt生效的开始时间，意味在这个时间之前验证jwt都是无效的
                    }
                    return jwtBuilder.compact();
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
            /**
             * 获取用户
             * @param token

             * @return
             */
            public static String getUsername(String token){
                return parseJwt(token).getSubject();
            }

            /**
             * 获取用户id
             * @param token
             * @return
             */
            public static String getUserId(String token){
                Claims claims = parseJwt(token);
                assert claims != null;
                byte[] userIds = Base64.getDecoder().decode(claims.get("userId", String.class));

                return  new String(userIds);
            }

            /**
             * token是否过期
             * @param token
             * @return
             */
            public static boolean isExpiration(String token){
                return parseJwt(token).getExpiration().before(new Date());
            }
    }



